home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 242 / Issue 242 - April 2008 - DPCS0408DVD.ISO / Software Money Savers / VirtualDub / Source / VirtualDub-1.7.7-src.7z / src / Asuka / source / glc_atifs.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2006-11-28  |  13.2 KB  |  488 lines

  1. #include "stdafx.h"
  2. #include "glc.h"
  3. #include <vd2/system/vdalloc.h>
  4. #include <vd2/Riza/opengl.h>
  5.  
  6. using namespace GLCIL;
  7.  
  8. namespace {
  9.     enum {
  10.         kChannelOpAdd,
  11.         kChannelOpSub,
  12.         kChannelOpMul,
  13.         kChannelOpMad,
  14.         kChannelOpLerp,
  15.         kChannelOpMov,
  16.         kChannelOpCnd,
  17.         kChannelOpCnd0,
  18.         kChannelOpDot2Add,
  19.         kChannelOpDot3,
  20.         kChannelOpDot4,
  21.         kChannelOpTexcrd,
  22.         kChannelOpTexld,
  23.         kChannelOpMask            = 0x0F,
  24.         kChannelOpModScaleMask    = 0x70,
  25.         kChannelOpModScaleX2    = 0x10,
  26.         kChannelOpModScaleX4    = 0x20,
  27.         kChannelOpModScaleX8    = 0x30,
  28.         kChannelOpModScaleD2    = 0x40,
  29.         kChannelOpModScaleD4    = 0x50,
  30.         kChannelOpModScaleD8    = 0x60,
  31.         kChannelOpModSaturate    = 0x80
  32.     };
  33.  
  34.     enum {
  35.         kChanRegR0,
  36.         kChanRegR1,
  37.         kChanRegR2,
  38.         kChanRegR3,
  39.         kChanRegR4,
  40.         kChanRegR5,
  41.         kChanRegC0,
  42.         kChanRegC1,
  43.         kChanRegC2,
  44.         kChanRegC3,
  45.         kChanRegC4,
  46.         kChanRegC5,
  47.         kChanRegC6,
  48.         kChanRegC7,
  49.         kChanRegZero,
  50.         kChanRegOne,
  51.         kChanRegV0,
  52.         kChanRegV1,
  53.         kChanSrcMod2X        = 0x100,
  54.         kChanSrcModComp        = 0x200,
  55.         kChanSrcModNegate    = 0x400,
  56.         kChanSrcModBias        = 0x800,
  57.         kChanSrcSwizzleRed        = 0x1000,
  58.         kChanSrcSwizzleGreen    = 0x2000,
  59.         kChanSrcSwizzleBlue        = 0x3000,
  60.         kChanSrcSwizzleAlpha    = 0x4000,
  61.         kChanDstMaskRed        = 0x10,
  62.         kChanDstMaskGreen    = 0x20,
  63.         kChanDstMaskBlue    = 0x40,
  64.         kChanDstMaskAlpha    = 0x80
  65.     };
  66.  
  67.     struct ATIFSChannelOp {
  68.         uint8 mOpcode;
  69.         uint8 mDstArg;
  70.         int mSrcArgCnt;
  71.         uint16 mSrcArgs[3];
  72.  
  73.         void Write(FILE *f) const {
  74.             fprintf(f, "0x%02x,0x%02x,", mOpcode, mDstArg);
  75.  
  76.             for(int i=0; i<mSrcArgCnt; ++i)
  77.                 fprintf(f, "0x%02x,0x%02x,", mSrcArgs[i] & 0xff, mSrcArgs[i] >> 8);
  78.         }
  79.     };
  80.  
  81.     enum {
  82.         kTexAddrT0            = 0x00,
  83.         kTexAddrT1            = 0x01,
  84.         kTexAddrT2            = 0x02,
  85.         kTexAddrT3            = 0x03,
  86.         kTexAddrT4            = 0x04,
  87.         kTexAddrT5            = 0x05,
  88.         kTexAddrR0            = 0x08,
  89.         kTexAddrR1            = 0x09,
  90.         kTexAddrR2            = 0x0A,
  91.         kTexAddrR3            = 0x0B,
  92.         kTexAddrR4            = 0x0C,
  93.         kTexAddrR5            = 0x0D,
  94.         kTexSwizzleXYZ        = 0x00,
  95.         kTexSwizzleXYW        = 0x10,
  96.         kTexSwizzleXYZ_DZ    = 0x20,
  97.         kTexSwizzleXYW_DW    = 0x30,
  98.         kTexModeTexcrd        = 0x40,
  99.         kTexModeTexld        = 0x80
  100.     };
  101.  
  102.     struct ATIFragmentShaderPhase {
  103.         uint8    mTexOps[6];
  104.         vdfastvector<ATIFSChannelOp> mOps;
  105.  
  106.         ATIFragmentShaderPhase() {
  107.             memset(mTexOps, 0, sizeof mTexOps);
  108.         }
  109.  
  110.         void Write(FILE *f) const {
  111.             fprintf(f, "\t%d,", (int)mOps.size());
  112.  
  113.             for(int i=0; i<6; ++i)
  114.                 fprintf(f, "0x%02x,", mTexOps[i]);
  115.  
  116.             fputs("\n", f);
  117.             for(int i=0, cnt=mOps.size(); i<cnt; ++i) {
  118.                 fputs("\t", f);
  119.                 mOps[i].Write(f);
  120.                 fputs("\n", f);
  121.             }
  122.         }
  123.     };
  124.  
  125.     class ATIFragmentShader : public vdrefcounted<IGLCFragmentShader> {
  126.     public:
  127.         ATIFragmentShader() : mPhaseCount(1) {}
  128.  
  129.         const char *GetTypeString() {
  130.             return "kVDOpenGLFragmentShaderModeATIFS";
  131.         }
  132.  
  133.         void Write(FILE *f, const char *sym) {
  134.             if (!mConstants.empty()) {
  135.                 fprintf(f, "static const float %s_constants[][4]={\n", sym, (int)mConstants.size() >> 2);
  136.                 for(int i=0; i<(int)mConstants.size(); i += 4) {
  137.                     fprintf(f, "\t{");
  138.  
  139.                     for(int j=0; j<4; ++j) {
  140.                         char buf[512];
  141.                         sprintf(buf, "%g", mConstants[i+j]);
  142.                         if (strchr(buf, '.'))
  143.                             fprintf(f, " %sf", buf);
  144.                         else
  145.                             fprintf(f, " %s.f", buf);
  146.  
  147.                         if (j != 3)
  148.                             putc(',', f);
  149.                     }
  150.  
  151.                     fprintf(f, " },\n");
  152.                 };
  153.                 fprintf(f, "};\n");
  154.             }
  155.  
  156.             fprintf(f, "static const uint8 %s_bytecode[]={\n", sym);
  157.             for(int i=0; i<mPhaseCount; ++i) {
  158.                 mPhases[i].Write(f);
  159.             }
  160.             fprintf(f, "\t0\n");
  161.             fprintf(f, "};\n");
  162.  
  163.             fprintf(f, "static const struct VDOpenGLATIFragmentShaderConfig %s[]={\n", sym);
  164.             fprintf(f, "\t%d, \n", (int)mConstants.size() >> 2);
  165.             if (mConstants.empty())
  166.                 fprintf(f, "NULL, ");
  167.             else
  168.                 fprintf(f, "%s_constants, ", sym);
  169.             fprintf(f, "%s_bytecode\n", sym);
  170.             fprintf(f, "};\n");
  171.         }
  172.  
  173.     public:
  174.         int mPhaseCount;
  175.         ATIFragmentShaderPhase mPhases[2];
  176.         vdfastvector<float> mConstants;
  177.     };
  178. }
  179.  
  180. IGLCFragmentShader *CompileFragmentShaderATIFragmentShader(GLCErrorSink& errout, const GLCFragmentShader& shader) {
  181.     vdautoptr<ATIFragmentShader> out(new ATIFragmentShader);
  182.  
  183.     bool secondPhase = false;
  184.  
  185.     int constant_assignment[16] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
  186.     int constantCount = 0;
  187.  
  188.     bool pairColorNext = true;
  189.     int phasePairCount = 0;
  190.  
  191.     GLCFragmentShader::FragmentOps::const_iterator it(shader.mOps.begin()), itEnd(shader.mOps.end());
  192.     for(; it!=itEnd; ++it) {
  193.         const GLCFragmentOp& srcop = *it;
  194.         int atiop = 0;
  195.         int argcnt = 0;
  196.  
  197.         if (srcop.mInsn == kFSOpPhase) {
  198.             if (secondPhase)
  199.                 errout.ThrowError(srcop.mLocation, "Second pass already started");
  200.  
  201.             out->mPhaseCount = 2;
  202.             secondPhase = true;
  203.             pairColorNext = true;
  204.             phasePairCount = 0;
  205.             continue;
  206.         }
  207.  
  208.         if (srcop.mInsn == kFSOpTexld2Arg) {
  209.             const GLCDestArg& opdst = srcop.mDstArgs[0];
  210.             const GLCSourceArg& tcsrc = srcop.mSrcArgs[0];
  211.  
  212.             if (opdst.mWriteMask != 15)
  213.                 errout.ThrowError(srcop.mLocation, "texld cannot be used with a write mask");
  214.  
  215.             if ((opdst.mReg & kRegTypeMask) != kRegR0)
  216.                 errout.ThrowError(srcop.mLocation, "texld destination must be a temporary register");
  217.  
  218.             int index = opdst.mReg - kRegR0;
  219.  
  220.             if (out->mPhases[secondPhase].mTexOps[index])
  221.                 errout.ThrowError(srcop.mLocation, "Destination already used in a texld or texcrd instruction in this phase");
  222.  
  223.             uint8 encoding = 0;
  224.  
  225.             switch(tcsrc.mReg & kRegTypeMask) {
  226.                 case kRegR0:
  227.                     if (!secondPhase)
  228.                         errout.ThrowError(srcop.mLocation, "Dependent texture reads can only occur in second phase");
  229.  
  230.                     encoding = kTexAddrR0 + (tcsrc.mReg - kRegR0);
  231.                     break;
  232.                 case kRegT0:
  233.                     encoding = kTexAddrT0 + (tcsrc.mReg - kRegT0);
  234.                     break;
  235.                 default:
  236.                     errout.ThrowError(srcop.mLocation, "texld source must be a temporary register (rn) or a texture coordinate register (tn)");
  237.             }
  238.  
  239.             if ((tcsrc.mSwizzle & 0x3f) == kSwizzleRGB && tcsrc.mSize >= 3)
  240.                 encoding |= kTexSwizzleXYZ;
  241.             else if ((tcsrc.mSwizzle & 0x3f) == 0x34 && tcsrc.mSize >= 3)
  242.                 encoding |= kTexSwizzleXYW;
  243.             else
  244.                 errout.ThrowError(srcop.mLocation, "Swizzle on texture coordinate source must be .xyz or .xyw");
  245.  
  246.             out->mPhases[secondPhase].mTexOps[index] = encoding | kTexModeTexld;
  247.             continue;
  248.         }
  249.  
  250.         if (srcop.mInsn == kFSOpTexcrd) {
  251.             const GLCDestArg& opdst = srcop.mDstArgs[0];
  252.             const GLCSourceArg& tcsrc = srcop.mSrcArgs[0];
  253.  
  254.             if (opdst.mWriteMask != 15)
  255.                 errout.ThrowError(srcop.mLocation, "'texcrd' cannot be used with a write mask");
  256.  
  257.             if ((opdst.mReg & kRegTypeMask) != kRegR0)
  258.                 errout.ThrowError(srcop.mLocation, "'texcrd' destination must be a temporary register");
  259.  
  260.             int index = opdst.mReg - kRegR0;
  261.  
  262.             if (out->mPhases[secondPhase].mTexOps[index])
  263.                 errout.ThrowError(srcop.mLocation, "Destination already used in a texld or texcrd instruction in this phase");
  264.  
  265.             uint8 encoding = 0;
  266.  
  267.             switch(tcsrc.mReg & kRegTypeMask) {
  268.                 case kRegR0:
  269.                     if (!secondPhase)
  270.                         errout.ThrowError(srcop.mLocation, "'texcrd' cannot reference temporary register in phase 1");
  271.  
  272.                     encoding = kTexAddrR0 + (tcsrc.mReg - kRegR0);
  273.                     break;
  274.                 case kRegT0:
  275.                     encoding = kTexAddrT0 + (tcsrc.mReg - kRegT0);
  276.                     break;
  277.                 default:
  278.                     errout.ThrowError(srcop.mLocation, "'texld': Source must be a temporary register (rn) or a texture coordinate register (tn)");
  279.             }
  280.  
  281.             if ((tcsrc.mSwizzle & 0x3f) == kSwizzleRGB && tcsrc.mSize >= 3)
  282.                 encoding |= kTexSwizzleXYZ;
  283.             else if ((tcsrc.mSwizzle & 0x3f) == 0x34 && tcsrc.mSize >= 3)
  284.                 encoding |= kTexSwizzleXYW;
  285.             else
  286.                 errout.ThrowError(srcop.mLocation, "Swizzle on texture coordinate source must be .xyz or .xyw");
  287.  
  288.             out->mPhases[secondPhase].mTexOps[index] = encoding | kTexModeTexcrd;
  289.             continue;
  290.         }
  291.  
  292.         switch(srcop.mInsn) {
  293.             case kFSOpMov:
  294.                 atiop = kChannelOpMov;
  295.                 argcnt = 1;
  296.                 break;
  297.             case kFSOpAdd:
  298.                 atiop = kChannelOpAdd;
  299.                 argcnt = 2;
  300.                 break;
  301.             case kFSOpSub:
  302.                 atiop = kChannelOpSub;
  303.                 argcnt = 2;
  304.                 break;
  305.             case kFSOpMul:
  306.                 atiop = kChannelOpMul;
  307.                 argcnt = 2;
  308.                 break;
  309.             case kFSOpMad:
  310.                 atiop = kChannelOpMad;
  311.                 argcnt = 3;
  312.                 break;
  313.             case kFSOpLrp:
  314.                 atiop = kChannelOpLerp;
  315.                 argcnt = 3;
  316.                 break;
  317.             case kFSOpDp3:
  318.                 atiop = kChannelOpDot3;
  319.                 argcnt = 2;
  320.                 break;
  321.             case kFSOpDp4:
  322.                 atiop = kChannelOpDot4;
  323.                 argcnt = 2;
  324.                 break;
  325.  
  326.             default:
  327.                 errout.ThrowError(srcop.mLocation, "Instruction not allowed in ATI_fragment_shader profile");
  328.         }
  329.  
  330.         ATIFSChannelOp op;
  331.  
  332.         // convert destination argument
  333.         const GLCDestArg& dstarg = srcop.mDstArgs[0];
  334.         op.mDstArg = 0;
  335.  
  336.         switch(dstarg.mReg & kRegTypeMask) {
  337.             case kRegT0:
  338.                 errout.ThrowError(srcop.mLocation, "Texture coordinate register cannot be used as destination");
  339.                 break;
  340.             case kRegC0:
  341.                 errout.ThrowError(srcop.mLocation, "Constant register cannot be used as destination");
  342.                 break;
  343.             case kRegR0:
  344.                 op.mDstArg = kChanRegR0 + (dstarg.mReg - kRegR0);
  345.                 break;
  346.             case kRegV0:
  347.                 errout.ThrowError(srcop.mLocation, "Interpolator register cannot be used as destination");
  348.                 break;
  349.         }
  350.  
  351.         // convert destination write mask
  352.         if (dstarg.mWriteMask & 1)
  353.             op.mDstArg |= kChanDstMaskRed;
  354.         if (dstarg.mWriteMask & 2)
  355.             op.mDstArg |= kChanDstMaskGreen;
  356.         if (dstarg.mWriteMask & 4)
  357.             op.mDstArg |= kChanDstMaskBlue;
  358.         if (dstarg.mWriteMask & 8)
  359.             op.mDstArg |= kChanDstMaskAlpha;
  360.  
  361.         bool isDot = (atiop == kChannelOpDot3 || atiop == kChannelOpDot4);
  362.         bool isColor = (dstarg.mWriteMask & 7) != 0 || isDot;
  363.         bool isAlpha = (dstarg.mWriteMask & 8) != 0 || atiop == kChannelOpDot4;
  364.  
  365.         if (srcop.mbCoIssue) {
  366.             if (isColor && isAlpha)
  367.                 errout.ThrowError(srcop.mLocation, "A color+alpha instruction cannot be co-issued");
  368.  
  369.             if (isColor)
  370.                 errout.ThrowError(srcop.mLocation, "A color instruction must be the first in a co-issued pair");
  371.  
  372.             if (isAlpha && pairColorNext)
  373.                 errout.ThrowError(srcop.mLocation, "Cannot co-issue two alpha instructions");
  374.         }
  375.  
  376.         if (isColor || (isAlpha && pairColorNext)) {
  377.             if (phasePairCount >= 8)
  378.                 errout.ThrowError(srcop.mLocation, "Instruction pair count exceeded for this phase (8 max)");
  379.             ++phasePairCount;
  380.         }
  381.  
  382.         pairColorNext = isAlpha;
  383.  
  384.         // convert instruction modifiers
  385.         op.mOpcode = atiop;
  386.  
  387.         if (srcop.mModifiers & ~(kInsnModD2 | kInsnModD4 | kInsnModD8 | kInsnModX2 | kInsnModX4 | kInsnModX8 | kInsnModSat))
  388.             errout.ThrowError(srcop.mLocation, "Unsupported instruction modifier");
  389.  
  390.         if (srcop.mModifiers & kInsnModD2)
  391.             op.mOpcode |= kChannelOpModScaleD2;
  392.         else if (srcop.mModifiers & kInsnModD4)
  393.             op.mOpcode |= kChannelOpModScaleD4;
  394.         else if (srcop.mModifiers & kInsnModD8)
  395.             op.mOpcode |= kChannelOpModScaleD8;
  396.         else if (srcop.mModifiers & kInsnModX2)
  397.             op.mOpcode |= kChannelOpModScaleX2;
  398.         else if (srcop.mModifiers & kInsnModX4)
  399.             op.mOpcode |= kChannelOpModScaleX4;
  400.         else if (srcop.mModifiers & kInsnModX8)
  401.             op.mOpcode |= kChannelOpModScaleX8;
  402.  
  403.         if (srcop.mModifiers & kInsnModSat)
  404.             op.mOpcode |= kChannelOpModSaturate;
  405.  
  406.         // convert source arguments
  407.         op.mSrcArgCnt = argcnt;
  408.         for(int i=0; i<argcnt; ++i) {
  409.             const GLCSourceArg& srcarg = srcop.mSrcArgs[i];
  410.             int atireg = 0;
  411.             int index = srcarg.mReg & 0xff;
  412.  
  413.             switch(srcarg.mReg & kRegTypeMask) {
  414.                 case kRegT0:
  415.                     errout.ThrowError(srcop.mLocation, "Texture coordinate register can only be used as an argument to texld or texcrd");
  416.                     break;
  417.                 case kRegC0:
  418.                     if (constant_assignment[index] < 0) {
  419.                         if (constantCount >= 8)
  420.                             errout.ThrowError(srcop.mLocation, "Constant count limit exceeded (8 max)");
  421.  
  422.                         constant_assignment[index] = constantCount++;
  423.                         out->mConstants.insert(out->mConstants.end(), shader.mConstants[index], shader.mConstants[index] + 4);
  424.                     }
  425.                     atireg = kChanRegC0 + constant_assignment[index];
  426.                     break;
  427.                 case kRegR0:
  428.                     atireg = kChanRegR0 + index;
  429.                     break;
  430.                 case kRegV0:
  431.                     atireg = kChanRegV0 + index;
  432.                     break;
  433.             }
  434.  
  435.             if (srcarg.mMods & ~(kRegModNegate | kRegModComplement | kRegModBias | kRegModX2))
  436.                 errout.ThrowError(srcop.mLocation, "Unsupported source modifier");
  437.  
  438.             if (srcarg.mMods & kRegModNegate)
  439.                 atireg |= kChanSrcModNegate;
  440.  
  441.             if (srcarg.mMods & kRegModComplement)
  442.                 atireg |= kChanSrcModComp;
  443.  
  444.             if (srcarg.mMods & kRegModBias)
  445.                 atireg |= kChanSrcModBias;
  446.  
  447.             if (srcarg.mMods & kRegModX2)
  448.                 atireg |= kChanSrcMod2X;
  449.  
  450.             switch(srcarg.mSwizzle) {
  451.                 case kSwizzleNone:
  452.                     break;
  453.  
  454.                 case kSwizzleRGB:
  455.                     if (isAlpha)
  456.                         errout.ThrowError(srcop.mLocation, "Cannot use .rgb swizzle with alpha instruction");
  457.                     break;
  458.  
  459.                 case kSwizzleRed:
  460.                     atireg |= kChanSrcSwizzleRed;
  461.                     break;
  462.                 case kSwizzleGreen:
  463.                     atireg |= kChanSrcSwizzleGreen;
  464.                     break;
  465.                 case kSwizzleBlue:
  466.                     atireg |= kChanSrcSwizzleBlue;
  467.                     break;
  468.                 case kSwizzleAlpha:
  469.                     atireg |= kChanSrcSwizzleAlpha;
  470.                     break;
  471.  
  472.                 default:
  473.                     errout.ThrowError(srcop.mLocation, "Swizzle not supported in ATI_fragment_shader profile");
  474.                     break;
  475.             }
  476.  
  477.             op.mSrcArgs[i] = atireg;
  478.         }
  479.  
  480.         for(int i=argcnt; i<3; ++i)
  481.             op.mSrcArgs[i] = 0;
  482.  
  483.         out->mPhases[secondPhase].mOps.push_back(op);
  484.     }
  485.  
  486.     return out.release();
  487. }
  488.